//
//  WJPDFSignatureDrawView.swift
//  PDFSign
//
//  Created by 李永彬 on 2025/9/23.
//

import UIKit

protocol WJPDFSignatureDrawViewProtocol: AnyObject {
    func tapDrawView()
}

class WJPDFSignatureDrawView: UIView {
    private var lines: [WJPDFDrawLine] = []
    private var currentLine: WJPDFDrawLine?
    
    var tapDrawViewClosure: (()-> Void)?
    
    // 线条属性
    var strokeColor: UIColor = UIColor(hex: "#000000") {
        didSet {
            if strokeColor.cgColor.alpha == 0 {
                strokeColor = oldValue
            }
        }
    }
    
    var lineWidth: CGFloat = 6 {
        didSet {
            lineWidth = max(1, min(lineWidth, 50))
        }
    }
    
    var isEraserMode: Bool = false {
        didSet {
            lineWidth = isEraserMode ? 20 : 6
        }
    }
    
    // 初始化
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    
    private func commonInit() {
        backgroundColor = UIColor(hex: "#FFFFFF")
        isMultipleTouchEnabled = false
        clipsToBounds = true
        setupGestures()
    }
    
    // 手势设置 - 添加点击手势
    private func setupGestures() {
        // 点击手势 - 处理单个点
        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        tap.cancelsTouchesInView = false
        tap.delegate = self
        addGestureRecognizer(tap)
        
        // 拖拽手势 - 处理线条
        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
        pan.cancelsTouchesInView = false
        pan.delegate = self
        addGestureRecognizer(pan)
    }
    
    // 点击手势处理 - 新增方法
    @objc private func handleTap(_ gesture: UITapGestureRecognizer) {
        guard !isEraserMode else { return }
        
        let point = gesture.location(in: self)
        guard bounds.contains(point) else { return }
        
        // 创建只包含一个点的线条
        let singlePointLine = WJPDFDrawLine(
            startPoint: point,
            color: strokeColor,
            width: lineWidth
        )
        lines.append(singlePointLine)
        setNeedsDisplay()
        
        tapDrawViewClosure?()
    }
    
    // 拖拽手势处理
    @objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
        let point = gesture.location(in: self)
        
        switch gesture.state {
        case .began:
            tapDrawViewClosure?()
            startDrawing(at: point)
        case .changed:
            continueDrawing(at: point)
        case .ended, .cancelled:
            finishDrawing(at: point)
        default:
            break
        }
    }
    
    private func startDrawing(at point: CGPoint) {
        if !isEraserMode, bounds.contains(point) {
            currentLine = WJPDFDrawLine(
                startPoint: point,
                color: strokeColor,
                width: lineWidth
            )
        } else if isEraserMode {
            erase(at: point)
        }
        setNeedsDisplay()
    }
    
    private func continueDrawing(at point: CGPoint) {
        if isEraserMode {
            erase(at: point)
        } else if let currentLine = currentLine, bounds.contains(point) {
            currentLine.addPoint(point)
        }
        setNeedsDisplay()
    }
    
    private func finishDrawing(at point: CGPoint) {
        if !isEraserMode, let currentLine = currentLine {
            currentLine.addPoint(point)
            if currentLine.isValid {
                lines.append(currentLine)
            }
            self.currentLine = nil
        } else if isEraserMode {
            erase(at: point)
        }
        setNeedsDisplay()
    }
    
    // 擦除功能
    private func erase(at point: CGPoint) {
        let eraserRadius = lineWidth / 2
        
        for line in lines {
            for (index, linePoint) in line.points.enumerated() {
                let distance = hypot(point.x - linePoint.x, point.y - linePoint.y)
                if distance <= eraserRadius {
                    line.erasePoint(at: index)
                }
            }
        }
    }
    
    // 绘制
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        guard let context = UIGraphicsGetCurrentContext() else { return }
        
        // 绘制所有已完成的线条
        for line in lines {
            drawSmoothLine(line, in: context)
        }
        
        // 绘制当前正在绘制的线条
        if let currentLine = currentLine, !isEraserMode {
            drawSmoothLine(currentLine, in: context)
        }
    }
    
    // 使用三次贝塞尔曲线绘制真正光滑的线条，并支持单个点的绘制
    private func drawSmoothLine(_ line: WJPDFDrawLine, in context: CGContext) {
        let segments = line.getVisibleSegments()
        guard !segments.isEmpty else { return }
        
        context.saveGState()
        context.setStrokeColor(line.color.cgColor)
        context.setLineWidth(line.width)
        context.setLineCap(.round)
        context.setLineJoin(.round)
        
        for segment in segments {
            guard !segment.isEmpty else { continue }
            
            // 单个点的情况：绘制一个圆形点
            if segment.count == 1 {
                let point = segment[0]
                let radius = line.width / 2
                context.beginPath()
                context.addArc(center: point, radius: radius, startAngle: 0, endAngle: .pi * 2, clockwise: true)
                context.fillPath()
                continue
            }
            
            // 为当前线段创建临时线条以计算控制点
            let tempLine = WJPDFDrawLine(startPoint: segment[0], color: line.color, width: line.width)
            for i in 1..<segment.count {
                tempLine.addPoint(segment[i])
            }
            
            context.beginPath()
            context.move(to: segment[0])
            
            // 使用三次贝塞尔曲线绘制
            if segment.count == 2 {
                // 两点之间使用直线，但保持圆角端点
                context.addLine(to: segment[1])
            } else {
                // 多点之间使用三次贝塞尔曲线，实现真正光滑的过渡
                for i in 1..<segment.count {
                    if i - 1 < tempLine.controlPoints.count {
                        let controlOut = tempLine.controlPoints[i-1].out
                        let controlIn = tempLine.controlPoints[i].in
                        context.addCurve(
                            to: segment[i],
                            control1: controlOut,
                            control2: controlIn
                        )
                    }
                }
            }
            
            context.strokePath()
        }
        
        context.restoreGState()
    }
    
    // 图片生成
    func generateSignatureImage() -> UIImage? {
        let contentRect = calculateContentBounds()
        guard !contentRect.isEmpty else { return nil }
        
        let margin: CGFloat = 50
        let drawingRect = contentRect.insetBy(dx: -margin, dy: -margin)
        
        UIGraphicsBeginImageContextWithOptions(drawingRect.size, false, UIScreen.main.scale)
        defer { UIGraphicsEndImageContext() }
        
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        
        context.translateBy(x: -drawingRect.origin.x, y: -drawingRect.origin.y)
        UIColor.clear.setFill()
        context.fill(bounds)
        
        for line in lines {
            drawSmoothLine(line, in: context)
        }
        
        return UIGraphicsGetImageFromCurrentImageContext()
    }
    
    // 计算内容边界
    private func calculateContentBounds() -> CGRect {
        var minX = CGFloat.greatestFiniteMagnitude
        var minY = CGFloat.greatestFiniteMagnitude
        var maxX = CGFloat.leastNormalMagnitude
        var maxY = CGFloat.leastNormalMagnitude
        var hasContent = false
        
        for line in lines {
            let visiblePoints = line.visiblePoints
            guard !visiblePoints.isEmpty else { continue }
            
            hasContent = true
            for point in visiblePoints {
                minX = min(minX, point.x)
                minY = min(minY, point.y)
                maxX = max(maxX, point.x)
                maxY = max(maxY, point.y)
            }
        }
        
        guard hasContent else { return .zero }
        
        let linePadding = lineWidth / 2
        return CGRect(
            x: minX - linePadding,
            y: minY - linePadding,
            width: maxX - minX + lineWidth,
            height: maxY - minY + lineWidth
        )
    }
    
    // 公共方法
    func clear() {
        lines.removeAll()
        currentLine = nil
        setNeedsDisplay()
    }
    
    func hasValidSignature() -> Bool {
        return lines.contains { $0.isValid }
    }
}

// 手势代理，确保手势能正常工作
extension WJPDFSignatureDrawView: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return false
    }
    
    // 允许同时识别点击和拖拽手势
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return false
    }
}

